package com.matrix.framework.core.listcrud.service.impl;

import com.matrix.framework.core.common.global.Pager;
import com.matrix.framework.core.listcrud.data.BaseData;
import com.matrix.framework.core.listcrud.service.IListCrudService;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 基于List的增删改查服务默认实现
 * 线程安全的内存数据存储实现
 *
 * Copyright © 海平面工作室 版权所有
 *
 * @param <T> 数据类型，必须继承BaseData
 * @Author: Leo
 * @Create: 2025/9/20 11:00
 * @Since 1.2
 */
public class ListCrudServiceImpl<T extends BaseData> implements IListCrudService<T> {
    
    /**
     * 数据存储容器，使用ConcurrentHashMap保证线程安全
     */
    private final Map<Long, T> dataMap = new ConcurrentHashMap<>();
    
    /**
     * 读写锁，用于保证复合操作的线程安全
     */
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    
    @Override
    public T save(T entity) {
        if (entity == null) {
            throw new IllegalArgumentException("保存的实体不能为null");
        }
        
        lock.writeLock().lock();
        try {
            // 新增操作：如果ID为null，需要生成新ID
            if (entity.getId() == null) {
                // 获取当前最大ID
                long maxId = dataMap.isEmpty() ? 0L : 
                    dataMap.keySet().stream()
                        .mapToLong(Long::longValue)
                        .max()
                        .orElse(0L);
                // 设置新ID为最大ID+1
                entity.setId(maxId + 1);
            }
            
            dataMap.put(entity.getId(), entity);
            return entity;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public List<T> saveAll(List<T> entities) {
        if (entities == null || entities.isEmpty()) {
            return new ArrayList<>();
        }
        
        lock.writeLock().lock();
        try {
            return entities.stream()
                    .map(this::saveWithoutLock)
                    .collect(Collectors.toList());
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    private T saveWithoutLock(T entity) {
        if (entity.getId() == null) {
            entity.toString(); // 触发ID生成
        }
        dataMap.put(entity.getId(), entity);
        return entity;
    }
    
    @Override
    public boolean deleteById(Long id) {
        if (id == null) {
            return false;
        }
        
        lock.writeLock().lock();
        try {
            return dataMap.remove(id) != null;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public boolean delete(T entity) {
        if (entity == null || entity.getId() == null) {
            return false;
        }
        return deleteById(entity.getId());
    }
    
    @Override
    public int deleteByIds(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return 0;
        }
        
        lock.writeLock().lock();
        try {
            int count = 0;
            for (Long id : ids) {
                if (dataMap.remove(id) != null) {
                    count++;
                }
            }
            return count;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public int deleteByCondition(Predicate<T> condition) {
        if (condition == null) {
            return 0;
        }
        
        lock.writeLock().lock();
        try {
            List<Long> idsToDelete = dataMap.values().stream()
                    .filter(condition)
                    .map(BaseData::getId)
                    .collect(Collectors.toList());
            
            return deleteByIds(idsToDelete);
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public void deleteAll() {
        lock.writeLock().lock();
        try {
            dataMap.clear();
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public Optional<T> findById(Long id) {
        if (id == null) {
            return Optional.empty();
        }
        
        lock.readLock().lock();
        try {
            return Optional.ofNullable(dataMap.get(id));
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public List<T> findAll() {
        lock.readLock().lock();
        try {
            return new ArrayList<>(dataMap.values());
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public List<T> findByCondition(Predicate<T> condition) {
        if (condition == null) {
            return findAll();
        }
        
        lock.readLock().lock();
        try {
            return dataMap.values().stream()
                    .filter(condition)
                    .collect(Collectors.toList());
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public Optional<T> findFirstByCondition(Predicate<T> condition) {
        if (condition == null) {
            return Optional.empty();
        }
        
        lock.readLock().lock();
        try {
            return dataMap.values().stream()
                    .filter(condition)
                    .findFirst();
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public Pager<T> findAll(Pager<T> pager) {
        return findByCondition(null, pager);
    }
    
    @Override
    public Pager<T> findByCondition(Predicate<T> condition, Pager<T> pager) {
        if (pager == null) {
            pager = new Pager<>();
            pager.setPage(1);
            pager.setPageSize(10);
        }
        
        lock.readLock().lock();
        try {
            List<T> allData = condition == null ? 
                    new ArrayList<>(dataMap.values()) : 
                    dataMap.values().stream().filter(condition).collect(Collectors.toList());
            
            // 如果Pager中有排序字段信息，可以在这里处理排序
            // 注意：这里假设Pager可能有排序相关的字段，具体根据实际Pager实现调整
            
            long total = allData.size();
            int offset = (pager.getPage() - 1) * pager.getPageSize();
            
            // 分页
            List<T> pageData = allData.stream()
                    .skip(offset)
                    .limit(pager.getPageSize())
                    .collect(Collectors.toList());
            
            // 设置返回结果
            Pager<T> result = new Pager<>();
            result.setPage(pager.getPage());
            result.setPageSize(pager.getPageSize());
            result.setTotal((int) total);
            result.setItems(pageData);
            
            return result;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 对数据进行排序
     */
    private List<T> sortData(List<T> data, String sortField, boolean ascending) {
        try {
            Comparator<T> comparator = createComparator(sortField);
            if (!ascending) {
                comparator = comparator.reversed();
            }
            return data.stream().sorted(comparator).collect(Collectors.toList());
        } catch (Exception e) {
            // 如果排序失败，返回原数据
            return data;
        }
    }
    
    /**
     * 创建字段比较器
     */
    @SuppressWarnings("unchecked")
    private Comparator<T> createComparator(String fieldName) {
        return (o1, o2) -> {
            try {
                Object value1 = getFieldValue(o1, fieldName);
                Object value2 = getFieldValue(o2, fieldName);
                
                if (value1 == null && value2 == null) return 0;
                if (value1 == null) return -1;
                if (value2 == null) return 1;
                
                if (value1 instanceof Comparable) {
                    return ((Comparable<Object>) value1).compareTo(value2);
                }
                
                return value1.toString().compareTo(value2.toString());
            } catch (Exception e) {
                return 0;
            }
        };
    }
    
    /**
     * 通过反射获取字段值
     */
    private Object getFieldValue(T obj, String fieldName) throws Exception {
        Field field = findField(obj.getClass(), fieldName);
        if (field == null) {
            return null;
        }
        
        field.setAccessible(true);
        return field.get(obj);
    }
    
    /**
     * 递归查找字段
     */
    private Field findField(Class<?> clazz, String fieldName) {
        while (clazz != null) {
            try {
                return clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            }
        }
        return null;
    }
    
    @Override
    public long count() {
        lock.readLock().lock();
        try {
            return dataMap.size();
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public long countByCondition(Predicate<T> condition) {
        if (condition == null) {
            return count();
        }
        
        lock.readLock().lock();
        try {
            return dataMap.values().stream()
                    .filter(condition)
                    .count();
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public boolean existsById(Long id) {
        if (id == null) {
            return false;
        }
        
        lock.readLock().lock();
        try {
            return dataMap.containsKey(id);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public boolean existsByCondition(Predicate<T> condition) {
        if (condition == null) {
            return count() > 0;
        }
        
        lock.readLock().lock();
        try {
            return dataMap.values().stream()
                    .anyMatch(condition);
        } finally {
            lock.readLock().unlock();
        }
    }
} 